Skip to content

Commit 34b7b2a

Browse files
committed
review adjustments
1 parent 5510d1f commit 34b7b2a

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

kitsune/sumo/email_utils.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.core import mail
77
from django.core.exceptions import ValidationError
88
from django.core.mail import EmailMultiAlternatives
9-
from django.core.validators import EmailValidator
9+
from django.core.validators import validate_email
1010
from django.template.loader import render_to_string
1111
from django.test.client import RequestFactory
1212
from django.utils import translation
@@ -15,15 +15,28 @@
1515

1616

1717
log = logging.getLogger("k.email")
18-
email_validator = EmailValidator()
1918

2019

21-
def is_valid_email(email):
20+
def normalize_gmail(email: str) -> str:
21+
"""
22+
Return the given email with periods removed from its "local part"
23+
if it's a gmail address, otherwise return it unchanged.
24+
"""
25+
if email.lower().endswith("@gmail.com"):
26+
# Periods are ignored in the "local part" of gmail addresses.
27+
# We need to remove them before using Django's "validate_email",
28+
# otherwise it might incorrectly raise a ValidationError.
29+
local_part, domain = email.rsplit("@", maxsplit=1)
30+
return f"{local_part.replace('.', '')}@{domain}"
31+
return email
32+
33+
34+
def is_valid_email(email: str) -> bool:
2235
"""
2336
Returns True if the given email address is valid, False otherwise.
2437
"""
2538
try:
26-
email_validator(email)
39+
validate_email(normalize_gmail(email))
2740
except ValidationError:
2841
return False
2942
return True
@@ -34,10 +47,18 @@ def send_messages(messages):
3447
if not messages:
3548
return
3649

50+
# Only send each message to its valid recipients,
51+
# excluding messages without any valid recipients.
52+
cleaned_messages = []
53+
for message in messages:
54+
# Remove invalid emails and normalize gmails.
55+
cleaned_to = [normalize_gmail(email) for email in message.to if is_valid_email(email)]
56+
if cleaned_to:
57+
message.to = cleaned_to
58+
cleaned_messages.append(message)
59+
3760
with mail.get_connection(fail_silently=True) as conn:
38-
conn.send_messages(
39-
list(msg for msg in messages if all(is_valid_email(email) for email in msg.to))
40-
)
61+
conn.send_messages(cleaned_messages)
4162

4263

4364
def safe_translation(f):

kitsune/sumo/tests/test_email_utils.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -138,25 +138,21 @@ def test_styles_inlining(self):
138138
class SendMessagesTests(TestCase):
139139

140140
@patch("kitsune.sumo.email_utils.mail")
141-
def test_when_messages_have_valid_email(self, mock_mail):
141+
def test_send_messages(self, mock_mail):
142142
from_email = "notifications@support.mozilla.org"
143143
messages = [
144-
EmailMultiAlternatives("Test", "Testing", from_email, ["ringo@beatles.org"]),
145-
EmailMultiAlternatives("Test", "Testing", from_email, ["george@beatles.org"]),
146-
EmailMultiAlternatives("Test", "Testing", from_email, ["paul@beatles.org"]),
144+
EmailMultiAlternatives("Test", "Testing", from_email, ["beatles"]),
145+
EmailMultiAlternatives(
146+
"Test", "Testing", from_email, ["george.harrison.@gmail.com", "ringo"]
147+
),
148+
EmailMultiAlternatives("Test", "Testing", from_email, ["paul.mccartney.@gmail.com"]),
149+
EmailMultiAlternatives(
150+
"Test", "Testing", from_email, ["ringo@beatles.com", "george@beatles.com"]
151+
),
147152
]
148153
send_messages(messages)
149154
send_messages_mock = mock_mail.get_connection().__enter__().send_messages
150-
send_messages_mock.assert_called_once_with(messages)
151-
152-
@patch("kitsune.sumo.email_utils.mail")
153-
def test_when_message_has_invalid_email(self, mock_mail):
154-
from_email = "notifications@support.mozilla.org"
155-
messages = [
156-
EmailMultiAlternatives("Test", "Testing", from_email, ["ringo@beatles.org"]),
157-
EmailMultiAlternatives("Test", "Testing", from_email, ["george.@beatles.org"]),
158-
EmailMultiAlternatives("Test", "Testing", from_email, ["paul@beatles.org"]),
159-
]
160-
send_messages(messages)
161-
send_messages_mock = mock_mail.get_connection().__enter__().send_messages
162-
send_messages_mock.assert_called_once_with([messages[0], messages[2]])
155+
send_messages_mock.assert_called_once_with([messages[1], messages[2], messages[3]])
156+
self.assertEqual(messages[1].to, ["georgeharrison@gmail.com"])
157+
self.assertEqual(messages[2].to, ["paulmccartney@gmail.com"])
158+
self.assertEqual(messages[3].to, ["ringo@beatles.com", "george@beatles.com"])

0 commit comments

Comments
 (0)